package org.xxpay.pay.channel.sqpay.util;

import cfca.sadk.algorithm.common.Mechanism;
import cfca.sadk.algorithm.common.PKIException;
import cfca.sadk.lib.crypto.JCrypto;
import cfca.sadk.system.FileHelper;
import cfca.sadk.util.*;
import cfca.sadk.x509.certificate.X509Cert;
import com.alibaba.dubbo.common.URL;
import sun.misc.BASE64Decoder;

import javax.crypto.spec.SecretKeySpec;
import java.io.FileInputStream;
import java.net.URLEncoder;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;


public class CFCARAUtil {
	private static final String deviceName = JCrypto.JSOFT_LIB;
	private static cfca.sadk.lib.crypto.Session session = null;
	
	static {
		try {
			JCrypto jCrypto = JCrypto.getInstance();
			jCrypto.initialize(deviceName, null);
			session = jCrypto.openSession(deviceName);
		} catch (PKIException e) {
			e.printStackTrace();
		}
	}

	
	/******* p1 *********/
	/**
	 * p1消息签名
	 * @param ：message 待签名消息
	 * @return
	 * @throws Exception
	 */
	public static String signMessageByP1(String message, String pfxPath, String passWord) throws Exception{
		PrivateKey userPriKey = KeyUtil.getPrivateKeyFromPFX(new FileInputStream(pfxPath), passWord);
		Signature signature = new Signature();
		byte[] base64P7SignedData = signature.p1SignMessage(Mechanism.SHA256_RSA, message.getBytes("UTF-8"), userPriKey, session);
		return new String(base64P7SignedData);
	}

	/**
	 * p1消息校验(公钥证书验签)
	 * @param ：beforeSignedData 签名原文
	 * @param ：afterSignedData base64签名结果
	 * @param :certPath 公钥证书路径
	 * @return
	 * @throws Exception
	 */
	public static boolean verifyMessageByP1(String beforeSignedData, String afterSignedData, String certPath) throws Exception{
		X509Cert cert = new X509Cert(new FileInputStream(certPath));
		PublicKey publicKey = cert.getPublicKey();
		Signature signature = new Signature();
		return signature.p1VerifyMessage(Mechanism.SHA256_RSA, beforeSignedData.getBytes("UTF-8"), afterSignedData.getBytes("UTF-8"), publicKey, session);
	}

	/**
	 * p1消息签名(私钥字符串签加签)
	 * @param message
	 * @param privateKey
	 * @return
	 * @throws Exception
     */
	public static String signMessageByP1AndPriKey(String message, String privateKey) throws Exception{
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec((new BASE64Decoder()).decodeBuffer(privateKey));
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PrivateKey userPriKey = keyFactory.generatePrivate(keySpec);
		Signature signature = new Signature();
		byte[] base64P7SignedData = signature.p1SignMessage(Mechanism.SHA1_RSA, message.getBytes("UTF-8"), userPriKey, session);
		return new String(base64P7SignedData);
	}

	/**
	 * p1消息校验(公钥字符串验签)
	 * @param beforeSignedData
	 * @param afterSignedData
	 * @param publicKeyStr
	 * @return
	 * @throws Exception
	 */
	public static boolean verifyMessageByP1AndPubKey(String beforeSignedData, String afterSignedData, String publicKeyStr) throws Exception{
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec((new BASE64Decoder()).decodeBuffer(publicKeyStr));  
        PublicKey publicKey = keyFactory.generatePublic(keySpec);  
		Signature signature = new Signature();
		return signature.p1VerifyMessage(Mechanism.SHA1_RSA, beforeSignedData.getBytes("UTF-8"), afterSignedData.getBytes("UTF-8"), publicKey, session);
	}
	
	/********* RSA_PKCS ***********/
	/**
	 *  RSA证书加密消息
	 *  RSA_PKCS公钥加密
	 * @param ：message 待加密数据
	 * @throws
	 */
	public static String encryptMessageByRSA_PKCS(String message, String certPath) throws Exception{
		X509Cert cert = new X509Cert(new FileInputStream(certPath));
		PublicKey userPubKey = cert.getPublicKey();
		Mechanism mechanism = new Mechanism(Mechanism.RSA_PKCS);
		byte[] encryptedData = EncryptUtil.encrypt(mechanism, userPubKey, message.getBytes("UTF-8"), session);
		return new String(encryptedData);
	}

	/**
	 * RSA证书解密消息
	 * RSA_PKCS私钥解密
	 * @param :key 指定算法配对的私钥对象
	 * @param ：message 待解密数据
	 * @throws Exception 
	 */
	public static String decryptMessageByRSA_PKCS(String message, String pfxPath, String passWord) throws Exception{
		PrivateKey userPriKey = KeyUtil.getPrivateKeyFromPFX(new FileInputStream(pfxPath), passWord);
		Mechanism mechanism = new Mechanism(Mechanism.RSA_PKCS);
		byte[] dataBytes = message.getBytes("UTF-8");
		byte[] encryptedData = EncryptUtil.decrypt(mechanism, userPriKey, dataBytes, session);
		return new String(encryptedData);
	}
	
	/********* RC4 **********/
	/**
	 * RSA证书加密消息
	 * RC4对称加密
	 * @param ：message 待加密数据
	 * @return
	 * @throws Exception
	 */
	public static String encryptMessageByRC4(String message, String pfxPath, String passWord) throws Exception{
		byte[] data = FileHelper.read(pfxPath);
		Key key = new SecretKeySpec(Base64.decode(Base64.encode(data)), "RC4");
		Mechanism mechanism = new Mechanism(Mechanism.RC4);
		byte[] dataBytes = message.getBytes("UTF-8");
		byte[] encryptedData = EncryptUtil.encrypt(mechanism, key, dataBytes, session);
		return new String(encryptedData);
      
	}

	/**
	 * RSA证书解密消息
	 * RC4对称解密
	 * @param ：message 待解密数据
	 * @return
	 * @throws Exception
	 */
	public static String decryptMessageByRC4(String message, String pfxPath, String passWord) throws Exception{
		byte[] data = FileHelper.read(pfxPath);
		Key key = new SecretKeySpec(Base64.decode(Base64.encode(data)), "RC4");
		Mechanism mechanism = new Mechanism(Mechanism.RC4);
		byte[] encryptedData = EncryptUtil.decrypt(mechanism, key, message.getBytes("UTF-8"), session);
        return new String(encryptedData);
	}
	
	/****** p7 ******/
	/**
	 * P7 分离式文件签名（签名）
	 */
	public static String signData(String toBeSigned, String certPath, String certPass) throws Exception {
		X509Cert cert = CertUtil.getCertFromPFX(certPath, certPass);
		PrivateKey priKey = KeyUtil.getPrivateKeyFromPFX(certPath, certPass);
		Signature signature = new Signature();
		return new String(signature.p7SignMessageDetach(Mechanism.SHA256_RSA, toBeSigned.getBytes("UTF8"), priKey, cert, session), "UTF8");
	}
	
	/**
	 * P7 分离式消息校验（验签）
	 */
	public static boolean verifySignature(String data, String signdata) throws Exception {
		Signature signature = new Signature();
		return signature.p7VerifyMessageDetach(data.getBytes("UTF8"), signdata.getBytes("UTF8"), session);
	}
	
	/**
	 * 消息数字信封（公钥加密）
	 */
	public static String encryptData(String data, String certPath) throws Exception {
		// X509Cert cert = CertUtil.getCertFromPFX(certPath, certPass);
		X509Cert cert = new X509Cert(new FileInputStream(certPath));
		X509Cert[] recvcerts = new X509Cert[]{ cert };
		return new String(EnvelopeUtil.envelopeMessage(data.getBytes("UTF8"), Mechanism.RC4, recvcerts, session), "UTF8");
	}
	
	/**
	 * 数据解密
	 */
	public static String decryptData(String encryptedData, String certPath, String certPass) throws Exception {
		PrivateKey priKey = KeyUtil.getPrivateKeyFromPFX(certPath, certPass);
		X509Cert cert = CertUtil.getCertFromPFX(certPath, certPass);
		return new String(EnvelopeUtil.openEvelopedMessage(encryptedData.getBytes("UTF8"), priKey, cert, session), "UTF8");
	}
	
	
	public static void main(String[] args) throws Exception {


		String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKkhOAvYkcjZPx8mw6I8dyvx5kl3" +
				"aTk5F9uCF+OVkifH2z7mCHbRPMOrk+69hQts0o0RV5KHLlZQ6lZnTay5D2c23Ga7ep9N8jKRqIOH" +
				"ascxv7sLW5OiO1NEqxCTq587x42pgRy7zB9qvzdBRedrYphy7hVnV/aT2b6wo6HXG0MnAgMBAAEC" +
				"gYAkiDRe+qyiwapMxEbFqGHlcB7aB50G6zooA/W9BvXG+fh1oaJ6Z7/EVC9kBjPSv/LK3dAYqnJr" +
				"2paDi1TP1jlpK7NYg0E98GiYZYoOWr5u4nwoQav1KPbR1JIR1oM7+m9nkgUEk3JB1aeQmm0BlLmp" +
				"+UPji57WGj+pnpeaUQ4/oQJBAOVSFfrQypobP5P4YW90kvAldE27aWK7CizTU3sjxwmwTFSV34Ue" +
				"XArGjOvEpxkdVzvaLiQ5Rk3ciFFpT96KSV0CQQC8znPu/+PdBprGFsfyjKKgKghH7gVEa552K/et" +
				"mPF7vap701Iu0K2/bj6EIg5OKTYqvy6q4VDXbTEx/sVDkcJTAkEAoQoHI27SiGxQNpJ7ojCEK56x" +
				"0RCmTk45NAdnnZcfZF9pCxGAuVP7oRmTxtH/4nQnWYG7W3bZNz6CgGFrVEVahQJAdnLjAq6gqnpJ" +
				"QTrrh7w5DlgwR8gIn+sQR7y/rrYD0Yik2vgxV9NtHWqxZ73h0aFDLUAxq9ydFfmX4nCeGwznpwJB" +
				"ANvnGKiiZsdOs76gHxlAVL7pmSwwMxNg4nEaI/Wm49ARAhykaIrlPotTGszesoZJcAGfO66OwIu5" +
				"ssNWzfrI+KI=";
		
		String plaintext = "merno=168893&time=20181130194621&content=测试姓名|1012|6214837520969000|1|50.02|201811296400|000|paytest";

		//签名
		String base64P7SignedData3 = URLEncoder.encode(signMessageByP1AndPriKey(plaintext,privateKey));

		System.out.println(base64P7SignedData3);

		//验签

		//验签
		String publicKeyStr = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApSC4H4PvPuS9GJq9chCHq"
				+ "PHb+MK2dYRwVlU+9LJHhEA0mbmkhbSyvcakHuvrXtrBCBt5GMSU2BQeZy2IqQoZDJ"
				+ "Cn5CHufgMUpyMD7qvRo+GOg3GRC3k506ebb/Od/LL0eMAcCiOcCC7HHiPGP44VtBs"
				+ "OgqX22/BSAxyK93bnQbb4+8sc4id0io403rLjBle7vIzrNJtqftuTSQJMm/OmRDvf"
				+ "hg0asdUZYCsb3TdhRqO5hblDl/s/5b6gFTYcgPAw9qKdknqAWGqHP/J6i3GDAqedq"
				+ "7lFuDvkqSnYnWgVzpv9luWzrvXYOl2K4fvDSl9JIXHUMMz9cELEJjmq7yM+fQIDAQ"
				+ "AB";


		//boolean verifyByp1PublicKeyStr = verifyMessageByP1AndPubKey(plaintext, base64P7SignedData3, publicKeyStr);
		//System.out.println("p1-PublicKeyStr:"+verifyByp1PublicKeyStr);


		/*String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKkhOAvYkcjZPx8mw6I8dyvx5kl3" +
				"aTk5F9uCF+OVkifH2z7mCHbRPMOrk+69hQts0o0RV5KHLlZQ6lZnTay5D2c23Ga7ep9N8jKRqIOH" +
				"ascxv7sLW5OiO1NEqxCTq587x42pgRy7zB9qvzdBRedrYphy7hVnV/aT2b6wo6HXG0MnAgMBAAEC" +
				"gYAkiDRe+qyiwapMxEbFqGHlcB7aB50G6zooA/W9BvXG+fh1oaJ6Z7/EVC9kBjPSv/LK3dAYqnJr" +
				"2paDi1TP1jlpK7NYg0E98GiYZYoOWr5u4nwoQav1KPbR1JIR1oM7+m9nkgUEk3JB1aeQmm0BlLmp" +
				"+UPji57WGj+pnpeaUQ4/oQJBAOVSFfrQypobP5P4YW90kvAldE27aWK7CizTU3sjxwmwTFSV34Ue" +
				"XArGjOvEpxkdVzvaLiQ5Rk3ciFFpT96KSV0CQQC8znPu/+PdBprGFsfyjKKgKghH7gVEa552K/et" +
				"mPF7vap701Iu0K2/bj6EIg5OKTYqvy6q4VDXbTEx/sVDkcJTAkEAoQoHI27SiGxQNpJ7ojCEK56x" +
				"0RCmTk45NAdnnZcfZF9pCxGAuVP7oRmTxtH/4nQnWYG7W3bZNz6CgGFrVEVahQJAdnLjAq6gqnpJ" +
				"QTrrh7w5DlgwR8gIn+sQR7y/rrYD0Yik2vgxV9NtHWqxZ73h0aFDLUAxq9ydFfmX4nCeGwznpwJB" +
				"ANvnGKiiZsdOs76gHxlAVL7pmSwwMxNg4nEaI/Wm49ARAhykaIrlPotTGszesoZJcAGfO66OwIu5" +
				"ssNWzfrI+KI=";
		String content = "12123";
		String s = signMessageByP2(content, privateKey);
		System.out.println("s=" + s);
		*/
	}
	
}
